#include "main.h"

int main(int argc, char *argv[])
{
    //检查参数数量合法性
    if (argc < 3 || argc >= 4)
    {
        printf("Usage: ./mycp file1 file2\n");
        return -1;
    }
    //检查路径合法性
    char *path1 = argv[1];
    char *path2 = argv[2];
    struct stat *buff = malloc(sizeof(struct stat));
    if (stat(path1, buff) == -1) //用stat检查路径1时出错
    {
        if (errno == ENOENT)
        {
            printf("ERROR: Source file does not exist!\n");
        }
        else
        {
            printf("ERROR: %s\n", strerror(errno));
        }
        return -1;
    }
    else if (S_ISDIR(buff->st_mode)) //路径1是目录
    {
        printf("ERROR: Source file is a directory!\n");
        return -1;
    }
    else if (!S_ISREG(buff->st_mode))//路径1不是目录, 但也不是常规文件
    {
        printf("ERROR: Source file is not a regular file!\n");
        return -1;
    }
    //路径1无误, 检查路径2
    if (stat(path2, buff) == 0)
    {
        //路径2存在
        if (S_ISDIR(buff->st_mode)) //路径2为目录
        {
            //生成路径2下的目标文件名, 并检查其合法性
            char *path2convert = pathconvert(path1, path2);
            if (stat(path2convert, buff) == -1)
            {
                if (errno == ENOENT)
                {
                    //路径2下没有与源文件同名的目标文件, 则此时创建新文件, 并将源文件复制
                    return copyandoutput(path1, path2convert, 'w');
                }
                else
                {
                    printf("ERROR: %s\n", strerror(errno));
                    exit(-1);
                }
            }
            else if (!S_ISREG(buff->st_mode))
            {
                //路径2下有与源文件同名的其它类型非常规文件(如: 目录, 设备等), 提示错误, 退出
                printf("ERROR: Filename confilicted.\n");
                exit(-1);
            }
            else
            {
                //路径2下存在与源文件同名的常规文件, 则可视为路径2为已存在文件的情况处理, 则将原始输入路径2替换为修改后的路径2, 按照原始输入路径2为已存在文件的情况处理
                path2 = path2convert;
            }
        }
        if (S_ISREG(buff->st_mode))
        {
            //路径2为常规文件, 询问覆盖或者在尾部写入
            char c;
            while (c != 'c' && c != 'C')
            {

                printf("Target file already exists, Do you want to:\n");
                printf("[O]verwrite/[A]ppend/[C]ancel ?\n"); //提示覆盖/合并/取消
                c = getchar();
                if (c != EOF || c != '\n') //清空输入缓冲区
                {
                    char d;
                    while (d != EOF && d != '\n')
                    {
                        d = getchar();
                    }
                }
                switch (c)
                {
                case 'a':
                case 'A':
                    return copyandoutput(path1, path2, 'a');
                case 'o':
                case 'O':
                    return copyandoutput(path1, path2, 'w');
                default:
                    break;
                }
            }
        }
        else
        {
            printf("ERROR: Filename confilicted.\n");
            return -1;
        }
    }
    else if (errno == ENOENT)
    {
        //路径2不存在, 则需判别路径2是指向一个未创建的新文件或是一个不存在的目录
        int len2 = strlen(path2);
        if (len2 == 0 || path2[len2 - 1] == '/')
        {
            printf("ERROR: Target path not exist.\n");
        }
        else
        {
            int index;
            for (index = len2 - 1; index >= 0; index--)
            {
                if (path2[index] == '/')
                {
                    break;
                }
            }
            if (index == -1)
            {
                //此时路径2为当前工作路径下的一个未创建的文件
                return copyandoutput(path1, path2, 'w');
            }
            else
            {
                char *path2cut = malloc(sizeof(char) * len2);
                strncpy(path2cut, path2, index);
                if ((stat(path2cut, buff) == 0) && (S_ISDIR(buff->st_mode) == 1))
                {
                    return copyandoutput(path1, path2, 'w');
                }
                else
                {
                    //路径2的上一级路径不存在, 或者上一级路径为非目录, 则此时路径2非法
                    printf("ERROR: Target path illegal.\n");
                }
            }
        }
    }
    else
    {
        //在检查路径2时发生了其它错误, 输出错误信息.
        printf("ERROR: %s\n", strerror(errno));
        exit(-1);
    }
    return 0;
}